﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zcu.PanelComposer.ViewModels.Core;
using Zcu.PanelComposer.Interfaces;
using System.ComponentModel.Composition;
using Caliburn.Micro;
using Zcu.PanelComposer.Models.Model;
using System.ComponentModel.DataAnnotations;
using Caliburn.Micro.Validation;
using Zcu.PanelComposer.ViewModels.Events;

namespace Zcu.PanelComposer.ViewModels
{
    /// <summary>
    /// ViewModel pro zalozeni noveho projektu.
    /// </summary>
    [Export(typeof(IModule))]
    public class NewProjectViewModel : ValidatingScreen<NewProjectViewModel>
    {
        #region Fields

        /// <summary>
        /// Reference na logger.
        /// </summary>
        private readonly ILog _log = LogManager.GetLog(typeof(NewProjectViewModel));

        /// <summary>
        /// Pocet pater.
        /// </summary>
        private int? _Floors;

        /// <summary>
        /// Nazev projektu.
        /// </summary>
        private string _ProjectName;

        /// <summary>
        /// Projekt 
        /// </summary>
        private Project _SelectedProject;

        #endregion // Fields

        #region Properties

        /// <summary>
        /// Pristup na databazi.
        /// </summary>
        [Import]
        public IRepository Repository { get; private set; }

        /// <summary>
        /// Nazev projektu.
        /// </summary>
        [Required]
        public string ProjectName
        {
            get { return _ProjectName; }
            set
            {
                if (_ProjectName != value) _ProjectName = value;
                NotifyOfPropertyChange(() => ProjectName);
                NotifyOfPropertyChange(() => CanSaveAction);
            }
        }

        /// <summary>
        /// Gets or sets the floors.
        /// </summary>
        /// <value>
        /// The floors.
        /// </value>
        [Required]
        public int? Floors
        {
            get { return _Floors; }
            set
            {
                if (_Floors != value) _Floors = value;
                NotifyOfPropertyChange(() => Floors);
                NotifyOfPropertyChange(() => CanSaveAction);
            }
        }


        /// <summary>
        /// Upravovany projekt.
        /// </summary>
        public Project SelectedProject
        {
            get { return _SelectedProject; }
            set
            {
                if (_SelectedProject != value) _SelectedProject = value;
                NotifyOfPropertyChange(() => SelectedProject);
            }
        }

        /// <summary>
        /// True, pokud editujeme, jinak False.
        /// </summary>
        public bool IsEditMode { get; private set; }

        #endregion

        #region Guard properties

        /// <summary>
        /// Guard vlastnost nad tlacitkem Save.
        /// </summary>
        public bool CanSaveAction { get { return !HasErrors; } }

        #endregion

        #region Constructor

        /// <summary>
        /// Konstruktor ViewModelu, prednastaveni pocatecnich hodnot.
        /// Nazev stranky (titulek), nazev modulu (kvuli navigaci) a poradni v menu.
        /// </summary>
        public NewProjectViewModel()
        {
            /// todo do resources
            DisplayName = "New Project";
            ModuleName = PageNames.NewProject;
            Order = 3;
            MenuVisible = false;
        }

        #endregion // Constructor

        #region Overrided methods

        /// <summary>
        /// Pri aktivaci okna zkontrolujeme zda jde o editaci ci zalozeni noveho.
        /// Nasledne nacteme data z projektu do ViewModelu.
        /// </summary>
        protected override void OnActivate()
        {
            base.OnActivate();

            // zjisteni jestli jde o editaci ci novy projekt
            if (IsEditMode = Context != null && Context is Project)
            {
                SelectedProject = (Project)Context;
            }
            else
            {
                SelectedProject = new Project();
            }

            // nacteni dat z instance projektu
            LoadDataFromProject();
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Akce, vyvolana stiskem tlacitka "Save project".
        /// Ulozeni dat.
        /// </summary>
        public void SaveAction()
        {
            try
            {
                if (SelectedProject.Floors != (int)Floors)
                {
                    SelectedProject.XamlTexture = null;
                    SelectedProject.Drawing = null;
                }

                SelectedProject.DisplayName = ProjectName;
                SelectedProject.Floors = (int)Floors;

                if (IsEditMode)
                {
                    SelectedProject.UpdatedDate = DateTime.Now;
                }
                else
                {
                    SelectedProject.CreatedDate = DateTime.Now;
                    Repository.Add<Project>(SelectedProject);
                }

                // commit do DB
                Repository.Commit();
                // zmena aktivniho projektu
                EventAggregator.Publish(new ActiveProjectEvent(SelectedProject));
                // presmerovani na detail projektu
                Navigate(PageNames.ProjectDetail);
            }
            catch (Exception ex)
            {
                _log.Error(ex);
                Repository.RollBackAll();
            }
        }

        /// <summary>
        /// Akce, vyvolana stiskem tlacitka "Back action".
        /// </summary>
        public void BackAction()
        {
            Navigate(this.SourcePage);
        }

        #endregion // Public methods

        #region Private methods

        /// <summary>
        /// Nacteni dat z projektu do ViewModelu.
        /// </summary>
        private void LoadDataFromProject()
        {
            ProjectName = SelectedProject.DisplayName;
            Floors = SelectedProject.Floors == 0 ? null : (int?)SelectedProject.Floors;
        }

        #endregion
    }
}
